/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ssp.service;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import ssp.event.EventQueue;
import ssp.utility.LoggingManager;

/**
 * サービス要求を管理するクラス
 * @author yamazaki
 */
public class RequestManager {
    
    /**
     * フロントエンドサーバの性能
     */
    private double capacity;
    
    /**
     * 利用可能数
     */
    private double availability;
    
    /**
     * ServiceEntryごとのサービス提供中ユーザ数のマップ
     */
    private Map<ServiceEntry, Integer> providingServiceMap;
    
    /**
     * コンストラクタ
     * @param capacity フロントエンドサーバの性能
     */
    public RequestManager(double capacity) {
        this.capacity = capacity;
        this.availability = capacity;
        this.providingServiceMap = new HashMap<>();
    }

    /**
     * @return the capacity
     */
    public double getCapacity() {
        return capacity;
    }

    /**
     * @return the availability
     */
    public double getAvailability() {
        return availability;
    }
    
    /**
     * 指定のServiceEntryを提供しているユーザ数を返す
     * @param entry ServiceEntry
     * @return サービスを提供中のユーザ数
     */
    public int getProvidingServiceNum(ServiceEntry entry) {
        return providingServiceMap.get(entry);
    }
    
    /**
     * 指定のServiceEntryの利用を開始する
     * @param entry ServiceEntry
     */
    protected boolean start(ServiceEntry entry) {
        if(availability - entry.getWorkload() > 0) {
            increaseMap(entry);
            availability -= entry.getWorkload();
            return true;
        }
        else {
            if(EventQueue.getINSTANCE().isIsLogging())
                LoggingManager.logging(Level.INFO, "Request to Service " + entry.getTypeID() + " is lost.", new Throwable());
            return false;
        }
    }
    
    /**
     * 指定のServiceEntryの利用を終える
     * @param entry ServiceEntry
     */
    protected void finish(ServiceEntry entry) {
        providingServiceMap.put(entry, providingServiceMap.get(entry) - 1);
        availability += entry.getWorkload();
    }
    
    /**
     * providingServiceMap内の指定のServiceEntryの数を増加させる
     * @param entry ServiceEntry
     */
    private void increaseMap(ServiceEntry entry) {
        if(!providingServiceMap.containsKey(entry)) {
            providingServiceMap.put(entry, 0);
        }
        providingServiceMap.put(entry, providingServiceMap.get(entry) + 1);
    }
    
}